# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.676.12.21+1.676.13.26 -> 1.676.12.22 # include/asm-ia64/machvec.h 1.5.1.1 -> 1.7 # arch/ia64/hp/sim/simscsi.c 1.1 -> (deleted) # arch/ia64/kernel/efi.c 1.7.1.1 -> 1.9 # include/asm-ia64/io.h 1.5.1.1 -> 1.7 # arch/ia64/hp/zx1/hpzx1_misc.c 1.1.1.1 -> 1.3 # include/asm-ia64/pal.h 1.4.1.1 -> 1.6 # include/asm-ia64/unistd.h 1.5.1.1 -> 1.7 # arch/ia64/hp/sim/simscsi.h 1.1 -> (deleted) # arch/ia64/hp/sim/simserial.c 1.2 -> (deleted) # arch/ia64/kernel/gate.S 1.6.1.1 -> 1.8 # arch/ia64/vmlinux.lds.S 1.6.1.1 -> 1.8 # arch/ia64/sn/kernel/setup.c 1.1.1.1 -> 1.3 # arch/ia64/mm/Makefile 1.1.1.1 -> 1.3 # arch/ia64/kernel/irq.c 1.7.1.1 -> 1.9 # arch/ia64/kernel/perfmon.c 1.7.1.2 -> 1.10 # include/asm-ia64/sal.h 1.7.1.1 -> 1.9 # arch/ia64/mm/init.c 1.7.1.2 -> 1.10 # arch/ia64/hp/sim/simeth.c 1.2 -> (deleted) # arch/ia64/kernel/ia64_ksyms.c 1.6.1.1 -> 1.8 # arch/ia64/kernel/iosapic.c 1.6.1.1 -> 1.8 # arch/ia64/kernel/acpi.c 1.6.1.3 -> 1.10 # arch/ia64/kernel/machvec.c 1.1.1.1 -> 1.3 # arch/ia64/config.in 1.13.1.1 -> 1.15 # arch/ia64/kernel/signal.c 1.7.1.1 -> 1.9 # arch/ia64/hp/common/sba_iommu.c 1.1.1.3 -> 1.4 # arch/ia64/ia32/sys_ia32.c 1.9.1.1 -> 1.11 # arch/ia64/lib/swiotlb.c 1.7.1.1 -> 1.9 # arch/ia64/hp/sim/Makefile 1.1.1.1 -> 1.3 # arch/ia64/kernel/pal.S 1.4.1.1 -> 1.6 # diff -Nru a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c --- a/arch/ia64/hp/sim/simeth.c Wed Oct 8 09:07:44 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,533 +0,0 @@ -/* - * Simulated Ethernet Driver - * - * Copyright (C) 1999-2001 Hewlett-Packard Co - * Copyright (C) 1999-2001 Stephane Eranain - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SIMETH_RECV_MAX 10 - -/* - * Maximum possible received frame for Ethernet. - * We preallocate an sk_buff of that size to avoid costly - * memcpy for temporary buffer into sk_buff. We do basically - * what's done in other drivers, like eepro with a ring. - * The difference is, of course, that we don't have real DMA !!! - */ -#define SIMETH_FRAME_SIZE ETH_FRAME_LEN - - -#define SSC_NETDEV_PROBE 100 -#define SSC_NETDEV_SEND 101 -#define SSC_NETDEV_RECV 102 -#define SSC_NETDEV_ATTACH 103 -#define SSC_NETDEV_DETACH 104 - -#define NETWORK_INTR 8 - -struct simeth_local { - struct net_device_stats stats; - int simfd; /* descriptor in the simulator */ -}; - -static int simeth_probe1(void); -static int simeth_open(struct net_device *dev); -static int simeth_close(struct net_device *dev); -static int simeth_tx(struct sk_buff *skb, struct net_device *dev); -static int simeth_rx(struct net_device *dev); -static struct net_device_stats *simeth_get_stats(struct net_device *dev); -static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static void set_multicast_list(struct net_device *dev); -static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr); - -static char *simeth_version="0.3"; - -/* - * This variable is used to establish a mapping between the Linux/ia64 kernel - * and the host linux kernel. - * - * As of today, we support only one card, even though most of the code - * is ready for many more. The mapping is then: - * linux/ia64 -> linux/x86 - * eth0 -> eth1 - * - * In the future, we some string operations, we could easily support up - * to 10 cards (0-9). - * - * The default mapping can be changed on the kernel command line by - * specifying simeth=ethX (or whatever string you want). - */ -static char *simeth_device="eth0"; /* default host interface to use */ - - - -static volatile unsigned int card_count; /* how many cards "found" so far */ -static int simeth_debug; /* set to 1 to get debug information */ - -/* - * Used to catch IFF_UP & IFF_DOWN events - */ -static struct notifier_block simeth_dev_notifier = { - simeth_device_event, - 0 -}; - - -/* - * Function used when using a kernel command line option. - * - * Format: simeth=interface_name (like eth0) - */ -static int __init -simeth_setup(char *str) -{ - simeth_device = str; - return 1; -} - -__setup("simeth=", simeth_setup); - -/* - * Function used to probe for simeth devices when not installed - * as a loadable module - */ - -int __init -simeth_probe (void) -{ - int r; - - printk("simeth: v%s\n", simeth_version); - - r = simeth_probe1(); - - if (r == 0) register_netdevice_notifier(&simeth_dev_notifier); - - return r; -} - -extern long ia64_ssc (long, long, long, long, int); -extern void ia64_ssc_connect_irq (long intr, long irq); - -static inline int -netdev_probe(char *name, unsigned char *ether) -{ - return ia64_ssc(__pa(name), __pa(ether), 0,0, SSC_NETDEV_PROBE); -} - - -static inline int -netdev_connect(int irq) -{ - /* XXX Fix me - * this does not support multiple cards - * also no return value - */ - ia64_ssc_connect_irq(NETWORK_INTR, irq); - return 0; -} - -static inline int -netdev_attach(int fd, int irq, unsigned int ipaddr) -{ - /* this puts the host interface in the right mode (start interupting) */ - return ia64_ssc(fd, ipaddr, 0,0, SSC_NETDEV_ATTACH); -} - - -static inline int -netdev_detach(int fd) -{ - /* - * inactivate the host interface (don't interrupt anymore) */ - return ia64_ssc(fd, 0,0,0, SSC_NETDEV_DETACH); -} - -static inline int -netdev_send(int fd, unsigned char *buf, unsigned int len) -{ - return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_SEND); -} - -static inline int -netdev_read(int fd, unsigned char *buf, unsigned int len) -{ - return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_RECV); -} - -/* - * Function shared with module code, so cannot be in init section - * - * So far this function "detects" only one card (test_&_set) but could - * be extended easily. - * - * Return: - * - -ENODEV is no device found - * - -ENOMEM is no more memory - * - 0 otherwise - */ -static int -simeth_probe1(void) -{ - unsigned char mac_addr[ETH_ALEN]; - struct simeth_local *local; - struct net_device *dev; - int fd, i; - - /* - * XXX Fix me - * let's support just one card for now - */ - if (test_and_set_bit(0, &card_count)) - return -ENODEV; - - /* - * check with the simulator for the device - */ - fd = netdev_probe(simeth_device, mac_addr); - if (fd == -1) - return -ENODEV; - - dev = init_etherdev(NULL, sizeof(struct simeth_local)); - if (!dev) - return -ENOMEM; - - memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr)); - - dev->irq = ia64_alloc_vector(); - - /* - * attach the interrupt in the simulator, this does enable interrupts - * until a netdev_attach() is called - */ - netdev_connect(dev->irq); - - memset(dev->priv, 0, sizeof(struct simeth_local)); - - local = dev->priv; - local->simfd = fd; /* keep track of underlying file descriptor */ - - dev->open = simeth_open; - dev->stop = simeth_close; - dev->hard_start_xmit = simeth_tx; - dev->get_stats = simeth_get_stats; - dev->set_multicast_list = set_multicast_list; /* no yet used */ - - /* Fill in the fields of the device structure with ethernet-generic values. */ - ether_setup(dev); - - printk("%s: hosteth=%s simfd=%d, HwAddr", dev->name, simeth_device, local->simfd); - for(i = 0; i < ETH_ALEN; i++) { - printk(" %2.2x", dev->dev_addr[i]); - } - printk(", IRQ %d\n", dev->irq); - - return 0; -} - -/* - * actually binds the device to an interrupt vector - */ -static int -simeth_open(struct net_device *dev) -{ - if (request_irq(dev->irq, simeth_interrupt, 0, "simeth", dev)) { - printk ("simeth: unable to get IRQ %d.\n", dev->irq); - return -EAGAIN; - } - - netif_start_queue(dev); - - return 0; -} - -/* copied from lapbether.c */ -static __inline__ int dev_is_ethdev(struct net_device *dev) -{ - return ( dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5)); -} - - -/* - * Handler for IFF_UP or IFF_DOWN - * - * The reason for that is that we don't want to be interrupted when the - * interface is down. There is no way to unconnect in the simualtor. Instead - * we use this function to shutdown packet processing in the frame filter - * in the simulator. Thus no interrupts are generated - * - * - * That's also the place where we pass the IP address of this device to the - * simulator so that that we can start filtering packets for it - * - * There may be a better way of doing this, but I don't know which yet. - */ -static int -simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr) -{ - struct net_device *dev = (struct net_device *)ptr; - struct simeth_local *local; - struct in_device *in_dev; - struct in_ifaddr **ifap = NULL; - struct in_ifaddr *ifa = NULL; - int r; - - - if ( ! dev ) { - printk(KERN_WARNING "simeth_device_event dev=0\n"); - return NOTIFY_DONE; - } - - if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE; - - /* - * Check whether or not it's for an ethernet device - * - * XXX Fixme: This works only as long as we support one - * type of ethernet device. - */ - if ( !dev_is_ethdev(dev) ) return NOTIFY_DONE; - - if ((in_dev=dev->ip_ptr) != NULL) { - for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) - if (strcmp(dev->name, ifa->ifa_label) == 0) break; - } - if ( ifa == NULL ) { - printk("simeth_open: can't find device %s's ifa\n", dev->name); - return NOTIFY_DONE; - } - - printk("simeth_device_event: %s ipaddr=0x%x\n", dev->name, htonl(ifa->ifa_local)); - - /* - * XXX Fix me - * if the device was up, and we're simply reconfiguring it, not sure - * we get DOWN then UP. - */ - - local = dev->priv; - /* now do it for real */ - r = event == NETDEV_UP ? - netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)): - netdev_detach(local->simfd); - - printk("simeth: netdev_attach/detach: event=%s ->%d\n", event == NETDEV_UP ? "attach":"detach", r); - - return NOTIFY_DONE; -} - -static int -simeth_close(struct net_device *dev) -{ - netif_stop_queue(dev); - - free_irq(dev->irq, dev); - - return 0; -} - -/* - * Only used for debug - */ -static void -frame_print(unsigned char *from, unsigned char *frame, int len) -{ - int i; - - printk("%s: (%d) %02x", from, len, frame[0] & 0xff); - for(i=1; i < 6; i++ ) { - printk(":%02x", frame[i] &0xff); - } - printk(" %2x", frame[6] &0xff); - for(i=7; i < 12; i++ ) { - printk(":%02x", frame[i] &0xff); - } - printk(" [%02x%02x]\n", frame[12], frame[13]); - - for(i=14; i < len; i++ ) { - printk("%02x ", frame[i] &0xff); - if ( (i%10)==0) printk("\n"); - } - printk("\n"); -} - - -/* - * Function used to transmit of frame, very last one on the path before - * going to the simulator. - */ -static int -simeth_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct simeth_local *local = (struct simeth_local *)dev->priv; - -#if 0 - /* ensure we have at least ETH_ZLEN bytes (min frame size) */ - unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - /* Where do the extra padding bytes comes from inthe skbuff ? */ -#else - /* the real driver in the host system is going to take care of that - * or maybe it's the NIC itself. - */ - unsigned int length = skb->len; -#endif - - local->stats.tx_bytes += skb->len; - local->stats.tx_packets++; - - - if (simeth_debug > 5) frame_print("simeth_tx", skb->data, length); - - netdev_send(local->simfd, skb->data, length); - - /* - * we are synchronous on write, so we don't simulate a - * trasnmit complete interrupt, thus we don't need to arm a tx - */ - - dev_kfree_skb(skb); - return 0; -} - -static inline struct sk_buff * -make_new_skb(struct net_device *dev) -{ - struct sk_buff *nskb; - - /* - * The +2 is used to make sure that the IP header is nicely - * aligned (on 4byte boundary I assume 14+2=16) - */ - nskb = dev_alloc_skb(SIMETH_FRAME_SIZE + 2); - if ( nskb == NULL ) { - printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); - return NULL; - } - nskb->dev = dev; - - skb_reserve(nskb, 2); /* Align IP on 16 byte boundaries */ - - skb_put(nskb,SIMETH_FRAME_SIZE); - - return nskb; -} - -/* - * called from interrupt handler to process a received frame - */ -static int -simeth_rx(struct net_device *dev) -{ - struct simeth_local *local; - struct sk_buff *skb; - int len; - int rcv_count = SIMETH_RECV_MAX; - - local = (struct simeth_local *)dev->priv; - /* - * the loop concept has been borrowed from other drivers - * looks to me like it's a throttling thing to avoid pushing to many - * packets at one time into the stack. Making sure we can process them - * upstream and make forward progress overall - */ - do { - if ( (skb=make_new_skb(dev)) == NULL ) { - printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); - local->stats.rx_dropped++; - return 0; - } - /* - * Read only one frame at a time - */ - len = netdev_read(local->simfd, skb->data, SIMETH_FRAME_SIZE); - if ( len == 0 ) { - if ( simeth_debug > 0 ) printk(KERN_WARNING "%s: count=%d netdev_read=0\n", dev->name, SIMETH_RECV_MAX-rcv_count); - break; - } -#if 0 - /* - * XXX Fix me - * Should really do a csum+copy here - */ - memcpy(skb->data, frame, len); -#endif - skb->protocol = eth_type_trans(skb, dev); - - if ( simeth_debug > 6 ) frame_print("simeth_rx", skb->data, len); - - /* - * push the packet up & trigger software interrupt - */ - netif_rx(skb); - - local->stats.rx_packets++; - local->stats.rx_bytes += len; - - } while ( --rcv_count ); - - return len; /* 0 = nothing left to read, otherwise, we can try again */ -} - -/* - * Interrupt handler (Yes, we can do it too !!!) - */ -static void -simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - - if ( dev == NULL ) { - printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq); - return; - } - - /* - * very simple loop because we get interrupts only when receving - */ - while (simeth_rx(dev)); -} - -static struct net_device_stats * -simeth_get_stats(struct net_device *dev) -{ - struct simeth_local *local = (struct simeth_local *) dev->priv; - - return &local->stats; -} - -/* fake multicast ability */ -static void -set_multicast_list(struct net_device *dev) -{ - printk(KERN_WARNING "%s: set_multicast_list called\n", dev->name); -} - -#ifdef CONFIG_NET_FASTROUTE -static int -simeth_accept_fastpath(struct net_device *dev, struct dst_entry *dst) -{ - printk(KERN_WARNING "%s: simeth_accept_fastpath called\n", dev->name); - return -1; -} -#endif - -__initcall(simeth_probe); diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Wed Oct 8 09:07:44 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,384 +0,0 @@ -/* - * Simulated SCSI driver. - * - * Copyright (C) 1999, 2001 Hewlett-Packard Co - * Copyright (C) 1999, 2001 David Mosberger-Tang - * Copyright (C) 1999 Stephane Eranian - * - * 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33 - */ -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "scsi.h" -#include "sd.h" -#include "hosts.h" -#include "simscsi.h" - -#define DEBUG_SIMSCSI 1 - -/* Simulator system calls: */ - -#define SSC_OPEN 50 -#define SSC_CLOSE 51 -#define SSC_READ 52 -#define SSC_WRITE 53 -#define SSC_GET_COMPLETION 54 -#define SSC_WAIT_COMPLETION 55 - -#define SSC_WRITE_ACCESS 2 -#define SSC_READ_ACCESS 1 - -#ifdef DEBUG_SIMSCSI - int simscsi_debug; -# define DBG simscsi_debug -#else -# define DBG 0 -#endif - -#if 0 -struct timer_list disk_timer; -#else -static void simscsi_interrupt (unsigned long val); -DECLARE_TASKLET(simscsi_tasklet, simscsi_interrupt, 0); -#endif - -struct disk_req { - unsigned long addr; - unsigned len; -}; - -struct disk_stat { - int fd; - unsigned count; -}; - -extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr); - -static int desc[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; - -static struct queue_entry { - Scsi_Cmnd *sc; -} queue[SIMSCSI_REQ_QUEUE_LEN]; - -static int rd, wr; -static atomic_t num_reqs = ATOMIC_INIT(0); - -/* base name for default disks */ -static char *simscsi_root = DEFAULT_SIMSCSI_ROOT; - -#define MAX_ROOT_LEN 128 - -/* - * used to setup a new base for disk images - * to use /foo/bar/disk[a-z] as disk images - * you have to specify simscsi=/foo/bar/disk on the command line - */ -static int __init -simscsi_setup (char *s) -{ - /* XXX Fix me we may need to strcpy() ? */ - if (strlen(s) > MAX_ROOT_LEN) { - printk("simscsi_setup: prefix too long---using default %s\n", simscsi_root); - } - simscsi_root = s; - return 1; -} - -__setup("simscsi=", simscsi_setup); - -static void -simscsi_interrupt (unsigned long val) -{ - unsigned long flags; - Scsi_Cmnd *sc; - - spin_lock_irqsave(&io_request_lock, flags); - { - while ((sc = queue[rd].sc) != 0) { - atomic_dec(&num_reqs); - queue[rd].sc = 0; - if (DBG) - printk("simscsi_interrupt: done with %ld\n", sc->serial_number); - (*sc->scsi_done)(sc); - rd = (rd + 1) % SIMSCSI_REQ_QUEUE_LEN; - } - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -int -simscsi_detect (Scsi_Host_Template *templ) -{ - templ->proc_name = "simscsi"; -#if 0 - init_timer(&disk_timer); - disk_timer.function = simscsi_interrupt; -#endif - return 1; /* fake one SCSI host adapter */ -} - -int -simscsi_release (struct Scsi_Host *host) -{ - return 0; /* this is easy... */ -} - -const char * -simscsi_info (struct Scsi_Host *host) -{ - return "simulated SCSI host adapter"; -} - -int -simscsi_abort (Scsi_Cmnd *cmd) -{ - printk ("simscsi_abort: unimplemented\n"); - return SCSI_ABORT_SUCCESS; -} - -int -simscsi_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) -{ - printk ("simscsi_reset: unimplemented\n"); - return SCSI_RESET_SUCCESS; -} - -int -simscsi_biosparam (Disk *disk, kdev_t n, int ip[]) -{ - int size = disk->capacity; - - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; - return 0; -} - -static void -simscsi_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset, unsigned long len) -{ - struct disk_stat stat; - struct disk_req req; - - req.addr = __pa(sc->request_buffer); - req.len = len; /* # of bytes to transfer */ - - if (sc->request_bufflen < req.len) - return; - - stat.fd = desc[sc->target]; - if (DBG) - printk("simscsi_%s @ %lx (off %lx, len %lu) ->", - mode == SSC_READ ? "read":"write", req.addr, offset, len); - ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); - ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); - - if (stat.count == req.len) { - sc->result = GOOD; - } else { - sc->result = DID_ERROR << 16; - } - if (DBG) - printk("%d\n", sc->result); -} - -static void -simscsi_sg_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset) -{ - int list_len = sc->use_sg; - struct scatterlist *sl = (struct scatterlist *)sc->buffer; - struct disk_stat stat; - struct disk_req req; - - stat.fd = desc[sc->target]; - - while (list_len) { - req.addr = __pa(sl->address); - req.len = sl->length; - if (DBG) - printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", - mode == SSC_READ ? "read":"write", req.addr, offset, - list_len, sl->length); - ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); - ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); - - /* should not happen in our case */ - if (stat.count != req.len) { - sc->result = DID_ERROR << 16; - return; - } - offset += sl->length; - sl++; - list_len--; - } - sc->result = GOOD; -} - -/* - * function handling both READ_6/WRITE_6 (non-scatter/gather mode) - * commands. - * Added 02/26/99 S.Eranian - */ -static void -simscsi_readwrite6 (Scsi_Cmnd *sc, int mode) -{ - unsigned long offset; - - offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512; - if (sc->use_sg > 0) - simscsi_sg_readwrite(sc, mode, offset); - else - simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512); -} - - -static void -simscsi_readwrite10 (Scsi_Cmnd *sc, int mode) -{ - unsigned long offset; - - offset = ( (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16) - | (sc->cmnd[4] << 8) | (sc->cmnd[5] << 0))*512; - if (sc->use_sg > 0) - simscsi_sg_readwrite(sc, mode, offset); - else - simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); -} - -int -simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) -{ - char fname[MAX_ROOT_LEN+16]; - char *buf; -#if DEBUG_SIMSCSI - register long sp asm ("sp"); - - if (DBG) - printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n", - sc->target, sc->cmnd[0], sc->serial_number, sp, done); -#endif - - sc->result = DID_BAD_TARGET << 16; - sc->scsi_done = done; - if (sc->target <= 7 && sc->lun == 0) { - switch (sc->cmnd[0]) { - case INQUIRY: - if (sc->request_bufflen < 35) { - break; - } - sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target); - desc[sc->target] = ia64_ssc (__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, - 0, 0, SSC_OPEN); - if (desc[sc->target] < 0) { - /* disk doesn't exist... */ - break; - } - buf = sc->request_buffer; - buf[0] = 0; /* magnetic disk */ - buf[1] = 0; /* not a removable medium */ - buf[2] = 2; /* SCSI-2 compliant device */ - buf[3] = 2; /* SCSI-2 response data format */ - buf[4] = 31; /* additional length (bytes) */ - buf[5] = 0; /* reserved */ - buf[6] = 0; /* reserved */ - buf[7] = 0; /* various flags */ - memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); - sc->result = GOOD; - break; - - case TEST_UNIT_READY: - sc->result = GOOD; - break; - - case READ_6: - if (desc[sc->target] < 0 ) - break; - simscsi_readwrite6(sc, SSC_READ); - break; - - case READ_10: - if (desc[sc->target] < 0 ) - break; - simscsi_readwrite10(sc, SSC_READ); - break; - - case WRITE_6: - if (desc[sc->target] < 0) - break; - simscsi_readwrite6(sc, SSC_WRITE); - break; - - case WRITE_10: - if (desc[sc->target] < 0) - break; - simscsi_readwrite10(sc, SSC_WRITE); - break; - - - case READ_CAPACITY: - if (desc[sc->target] < 0 || sc->request_bufflen < 8) { - break; - } - buf = sc->request_buffer; - - /* pretend to be a 1GB disk (partition table contains real stuff): */ - buf[0] = 0x00; - buf[1] = 0x1f; - buf[2] = 0xff; - buf[3] = 0xff; - /* set block size of 512 bytes: */ - buf[4] = 0; - buf[5] = 0; - buf[6] = 2; - buf[7] = 0; - sc->result = GOOD; - break; - - case MODE_SENSE: - printk("MODE_SENSE\n"); - break; - - case START_STOP: - printk("START_STOP\n"); - break; - - default: - panic("simscsi: unknown SCSI command %u\n", sc->cmnd[0]); - } - } - if (sc->result == DID_BAD_TARGET) { - sc->result |= DRIVER_SENSE << 24; - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = 0x00; - } - if (atomic_read(&num_reqs) >= SIMSCSI_REQ_QUEUE_LEN) { - panic("Attempt to queue command while command is pending!!"); - } - atomic_inc(&num_reqs); - queue[wr].sc = sc; - wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN; - -#if 0 - if (!timer_pending(&disk_timer)) { - disk_timer.expires = jiffies; - add_timer(&disk_timer); - } -#else - tasklet_schedule(&simscsi_tasklet); -#endif - return 0; -} - - -static Scsi_Host_Template driver_template = SIMSCSI; - -#include "scsi_module.c" diff -Nru a/arch/ia64/hp/sim/simscsi.h b/arch/ia64/hp/sim/simscsi.h --- a/arch/ia64/hp/sim/simscsi.h Wed Oct 8 09:07:44 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,39 +0,0 @@ -/* - * Simulated SCSI driver. - * - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang - */ -#ifndef SIMSCSI_H -#define SIMSCSI_H - -#define SIMSCSI_REQ_QUEUE_LEN 64 - -#define DEFAULT_SIMSCSI_ROOT "/var/ski-disks/sd" - -extern int simscsi_detect (Scsi_Host_Template *); -extern int simscsi_release (struct Scsi_Host *); -extern const char *simscsi_info (struct Scsi_Host *); -extern int simscsi_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -extern int simscsi_abort (Scsi_Cmnd *); -extern int simscsi_reset (Scsi_Cmnd *, unsigned int); -extern int simscsi_biosparam (Disk *, kdev_t, int[]); - -#define SIMSCSI { \ - detect: simscsi_detect, \ - release: simscsi_release, \ - info: simscsi_info, \ - queuecommand: simscsi_queuecommand, \ - abort: simscsi_abort, \ - reset: simscsi_reset, \ - bios_param: simscsi_biosparam, \ - can_queue: SIMSCSI_REQ_QUEUE_LEN, \ - this_id: -1, \ - sg_tablesize: SG_ALL, \ - cmd_per_lun: SIMSCSI_REQ_QUEUE_LEN, \ - present: 0, \ - unchecked_isa_dma: 0, \ - use_clustering: DISABLE_CLUSTERING \ -} - -#endif /* SIMSCSI_H */ diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c --- a/arch/ia64/hp/sim/simserial.c Wed Oct 8 09:07:44 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1095 +0,0 @@ -/* - * Simulated Serial Driver (fake serial) - * - * This driver is mostly used for bringup purposes and will go away. - * It has a strong dependency on the system console. All outputs - * are rerouted to the same facility as the one used by printk which, in our - * case means sys_sim.c console (goes via the simulator). The code hereafter - * is completely leveraged from the serial.c driver. - * - * Copyright (C) 1999-2000, 2002 Hewlett-Packard Co - * Stephane Eranian - * David Mosberger-Tang - * - * 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close(). - * 02/25/00 D. Mosberger Synced up with 2.3.99pre-5 version of serial.c. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#undef SIMSERIAL_DEBUG /* define this to get some debug information */ - -#define KEYBOARD_INTR 3 /* must match with simulator! */ - -#define NR_PORTS 1 /* only one port for now */ -#define SERIAL_INLINE 1 - -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) - -#define SSC_GETCHAR 21 - -extern long ia64_ssc (long, long, long, long, int); -extern void ia64_ssc_connect_irq (long intr, long irq); - -static char *serial_name = "SimSerial driver"; -static char *serial_version = "0.6"; - -/* - * This has been extracted from asm/serial.h. We need one eventually but - * I don't know exactly what we're going to put in it so just fake one - * for now. - */ -#define BASE_BAUD ( 1843200 / 16 ) - -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - -/* - * Most of the values here are meaningless to this particular driver. - * However some values must be preserved for the code (leveraged from serial.c - * to work correctly). - * port must not be 0 - * type must not be UNKNOWN - * So I picked arbitrary (guess from where?) values instead - */ -static struct serial_state rs_table[NR_PORTS]={ - /* UART CLK PORT IRQ FLAGS */ - { 0, BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS,0,PORT_16550 } /* ttyS0 */ -}; - -/* - * Just for the fun of it ! - */ -static struct serial_uart_config uart_config[] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "cirrus", 1, 0 }, - { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, - { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | - UART_STARTECH }, - { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, - { 0, 0} -}; - -static struct tty_driver serial_driver, callout_driver; -static int serial_refcount; - -static struct async_struct *IRQ_ports[NR_IRQS]; -static struct tty_struct *serial_table[NR_PORTS]; -static struct termios *serial_termios[NR_PORTS]; -static struct termios *serial_termios_locked[NR_PORTS]; - -static struct console *console; - -static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); - -extern struct console *console_drivers; /* from kernel/printk.c */ - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ -#ifdef SIMSERIAL_DEBUG - printk("rs_stop: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", - tty->stopped, tty->hw_stopped, tty->flow_stopped); -#endif - -} - -static void rs_start(struct tty_struct *tty) -{ -#if SIMSERIAL_DEBUG - printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", - tty->stopped, tty->hw_stopped, tty->flow_stopped); -#endif -} - -static void receive_chars(struct tty_struct *tty, struct pt_regs *regs) -{ - unsigned char ch; - static unsigned char seen_esc = 0; - - while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) { - if ( ch == 27 && seen_esc == 0 ) { - seen_esc = 1; - continue; - } else { - if ( seen_esc==1 && ch == 'O' ) { - seen_esc = 2; - continue; - } else if ( seen_esc == 2 ) { - if ( ch == 'P' ) show_state(); /* F1 key */ - if ( ch == 'Q' ) show_buffers(); /* F2 key */ - seen_esc = 0; - continue; - } - } - seen_esc = 0; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; - - *tty->flip.char_buf_ptr = ch; - - *tty->flip.flag_buf_ptr = 0; - - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - tty_flip_buffer_push(tty); -} - -/* - * This is the serial driver's interrupt routine for a single port - */ -static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) -{ - struct async_struct * info; - - /* - * I don't know exactly why they don't use the dev_id opaque data - * pointer instead of this extra lookup table - */ - info = IRQ_ports[irq]; - if (!info || !info->tty) { - printk("simrs_interrupt_single: info|tty=0 info=%p problem\n", info); - return; - } - /* - * pretty simple in our case, because we only get interrupts - * on inbound traffic - */ - receive_chars(info->tty, regs); -} - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -#if 0 -/* - * not really used in our situation so keep them commented out for now - */ -static DECLARE_TASK_QUEUE(tq_serial); /* used to be at the top of the file */ -static void do_serial_bh(void) -{ - run_task_queue(&tq_serial); - printk("do_serial_bh: called\n"); -} -#endif - -static void do_softint(void *private_) -{ - printk("simserial: do_softint called\n"); -} - -static void rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (!tty || !info->xmit.buf) return; - - save_flags(flags); cli(); - if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) { - restore_flags(flags); - return; - } - info->xmit.buf[info->xmit.head] = ch; - info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); - restore_flags(flags); -} - -static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) -{ - int count; - unsigned long flags; - - save_flags(flags); cli(); - - if (info->x_char) { - char c = info->x_char; - - console->write(console, &c, 1); - - info->state->icount.tx++; - info->x_char = 0; - - goto out; - } - - if (info->xmit.head == info->xmit.tail || info->tty->stopped || info->tty->hw_stopped) { -#ifdef SIMSERIAL_DEBUG - printk("transmit_chars: head=%d, tail=%d, stopped=%d\n", - info->xmit.head, info->xmit.tail, info->tty->stopped); -#endif - goto out; - } - /* - * We removed the loop and try to do it in to chunks. We need - * 2 operations maximum because it's a ring buffer. - * - * First from current to tail if possible. - * Then from the beginning of the buffer until necessary - */ - - count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE), - SERIAL_XMIT_SIZE - info->xmit.tail); - console->write(console, info->xmit.buf+info->xmit.tail, count); - - info->xmit.tail = (info->xmit.tail+count) & (SERIAL_XMIT_SIZE-1); - - /* - * We have more at the beginning of the buffer - */ - count = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count) { - console->write(console, info->xmit.buf, count); - info->xmit.tail += count; - } -out: - restore_flags(flags); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || - !info->xmit.buf) - return; - - transmit_chars(info, NULL); -} - - -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) -{ - int c, ret = 0; - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (!tty || !info->xmit.buf || !tmp_buf) return 0; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); - } - /* - * Hey, we transmit directly from here in our case - */ - if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) - && !tty->stopped && !tty->hw_stopped) { - transmit_chars(info, NULL); - } - return ret; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - save_flags(flags); cli(); - info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); - - wake_up_interruptible(&tty->write_wait); - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void rs_send_xchar(struct tty_struct *tty, char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - info->x_char = ch; - if (ch) { - /* - * I guess we could call console->write() directly but - * let's do that for now. - */ - transmit_chars(info, NULL); - } -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct * tty) -{ - if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); - - printk("simrs_throttle called\n"); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - printk("simrs_unthrottle called\n"); -} - -/* - * rs_break() --- routine which turns the break handling on or off - */ -static void rs_break(struct tty_struct *tty, int break_state) -{ -} - -static int rs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCMGET: - printk("rs_ioctl: TIOCMGET called\n"); - return -EINVAL; - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - printk("rs_ioctl: TIOCMBIS/BIC/SET called\n"); - return -EINVAL; - case TIOCGSERIAL: - printk("simrs_ioctl TIOCGSERIAL called\n"); - return 0; - case TIOCSSERIAL: - printk("simrs_ioctl TIOCSSERIAL called\n"); - return 0; - case TIOCSERCONFIG: - printk("rs_ioctl: TIOCSERCONFIG called\n"); - return -EINVAL; - - case TIOCSERGETLSR: /* Get line status register */ - printk("rs_ioctl: TIOCSERGETLSR called\n"); - return -EINVAL; - - case TIOCSERGSTRUCT: - printk("rs_ioctl: TIOCSERGSTRUCT called\n"); -#if 0 - if (copy_to_user((struct async_struct *) arg, - info, sizeof(struct async_struct))) - return -EFAULT; -#endif - return 0; - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - printk("rs_ioctl: TIOCMIWAIT: called\n"); - return 0; - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - printk("rs_ioctl: TIOCGICOUNT called\n"); - return 0; - - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - unsigned int cflag = tty->termios->c_cflag; - - if ( (cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rs_start(tty); - } -} -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct async_struct * info) -{ - unsigned long flags; - struct serial_state *state; - int retval; - - if (!(info->flags & ASYNC_INITIALIZED)) return; - - state = info->state; - -#ifdef SIMSERIAL_DEBUG - printk("Shutting down serial port %d (irq %d)....", info->line, - state->irq); -#endif - - save_flags(flags); cli(); /* Disable interrupts */ - - /* - * First unlink the serial port from the IRQ chain... - */ - if (info->next_port) - info->next_port->prev_port = info->prev_port; - if (info->prev_port) - info->prev_port->next_port = info->next_port; - else - IRQ_ports[state->irq] = info->next_port; - - /* - * Free the IRQ, if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - free_irq(state->irq, NULL); - retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(info), "serial", NULL); - - if (retval) - printk("serial shutdown: request_irq: error %d" - " Couldn't reacquire IRQ.\n", retval); - } else - free_irq(state->irq, NULL); - } - - if (info->xmit.buf) { - free_page((unsigned long) info->xmit.buf); - info->xmit.buf = 0; - } - - if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file * filp) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state; - unsigned long flags; - - if (!info ) return; - - state = info->state; - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { -#ifdef SIMSERIAL_DEBUG - printk("rs_close: hung_up\n"); -#endif - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } -#ifdef SIMSERIAL_DEBUG - printk("rs_close ttys%d, count = %d\n", info->line, state->count); -#endif - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("rs_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", - info->line, state->count); - state->count = 0; - } - if (state->count) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - info->flags |= ASYNC_CLOSING; - restore_flags(flags); - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - shutdown(info); - if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); - info->event = 0; - info->tty = 0; - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; -} - -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ -} - - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void rs_hangup(struct tty_struct *tty) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state = info->state; - -#ifdef SIMSERIAL_DEBUG - printk("rs_hangup: called\n"); -#endif - - state = info->state; - - rs_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) - return; - shutdown(info); - - info->event = 0; - state->count = 0; - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - - -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - if (sstate->info) { - *ret_info = sstate->info; - return 0; - } - info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } - memset(info, 0, sizeof(struct async_struct)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->magic = SERIAL_MAGIC; - info->port = sstate->port; - info->flags = sstate->flags; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->line = line; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->state = sstate; - if (sstate->info) { - kfree(info); - *ret_info = sstate->info; - return 0; - } - *ret_info = sstate->info = info; - return 0; -} - -static int -startup(struct async_struct *info) -{ - unsigned long flags; - int retval=0; - void (*handler)(int, void *, struct pt_regs *); - struct serial_state *state= info->state; - unsigned long page; - - page = get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - save_flags(flags); cli(); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - - if (!state->port || !state->type) { - if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - free_page(page); - goto errout; - } - if (info->xmit.buf) - free_page(page); - else - info->xmit.buf = (unsigned char *) page; - -#ifdef SIMSERIAL_DEBUG - printk("startup: ttys%d (irq %d)...", info->line, state->irq); -#endif - - /* - * Allocate the IRQ if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - retval = -EBUSY; - goto errout; - } else - handler = rs_interrupt_single; - - retval = request_irq(state->irq, handler, IRQ_T(info), - "simserial", NULL); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, - &info->tty->flags); - retval = 0; - } - goto errout; - } - } - - /* - * Insert serial port into IRQ chain. - */ - info->prev_port = 0; - info->next_port = IRQ_ports[state->irq]; - if (info->next_port) - info->next_port->prev_port = info; - IRQ_ports[state->irq] = info; - - if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); - - info->xmit.head = info->xmit.tail = 0; - -#if 0 - /* - * Set up serial timers... - */ - timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; - timer_active |= 1 << RS_TIMER; -#endif - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); - return 0; - -errout: - restore_flags(flags); - return retval; -} - - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int rs_open(struct tty_struct *tty, struct file * filp) -{ - struct async_struct *info; - int retval, line; - unsigned long page; - - MOD_INC_USE_COUNT; - line = MINOR(tty->device) - tty->driver.minor_start; - if ((line < 0) || (line >= NR_PORTS)) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - retval = get_async_struct(line, &info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - tty->driver_data = info; - info->tty = tty; - -#ifdef SIMSERIAL_DEBUG - printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, - info->state->count); -#endif - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - if (!tmp_buf) { - page = get_free_page(GFP_KERNEL); - if (!page) { - /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ - return -ENOMEM; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) { - /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ - return retval; - } - - if ((info->state->count == 1) && - (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->state->normal_termios; - else - *tty->termios = info->state->callout_termios; - } - - /* - * figure out which console to use (should be one already) - */ - console = console_drivers; - while (console) { - if ((console->flags & CON_ENABLED) && console->write) break; - console = console->next; - } - - info->session = current->session; - info->pgrp = current->pgrp; - -#ifdef SIMSERIAL_DEBUG - printk("rs_open ttys%d successful\n", info->line); -#endif - return 0; -} - -/* - * /proc fs routines.... - */ - -static inline int line_info(char *buf, struct serial_state *state) -{ - return sprintf(buf, "%d: uart:%s port:%lX irq:%d\n", - state->line, uart_config[state->type].name, - state->port, state->irq); -} - -static int rs_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - int i, len = 0, l; - off_t begin = 0; - - len += sprintf(page, "simserinfo:1.0 driver:%s\n", serial_version); - for (i = 0; i < NR_PORTS && len < 4000; i++) { - l = line_info(page + len, &rs_table[i]); - len += l; - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } - } - *eof = 1; -done: - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * --------------------------------------------------------------------- - * rs_init() and friends - * - * rs_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static inline void show_serial_version(void) -{ - printk(KERN_INFO "%s version %s with", serial_name, serial_version); - printk(" no serial options enabled\n"); -} - -/* - * The serial driver boot-time initialization code! - */ -static int __init -simrs_init (void) -{ - int i; - struct serial_state *state; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - - memset(&serial_driver, 0, sizeof(struct tty_driver)); - serial_driver.magic = TTY_DRIVER_MAGIC; - serial_driver.driver_name = "simserial"; - serial_driver.name = "ttyS"; - serial_driver.major = TTY_MAJOR; - serial_driver.minor_start = 64; - serial_driver.num = 1; - serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - serial_driver.subtype = SERIAL_TYPE_NORMAL; - serial_driver.init_termios = tty_std_termios; - serial_driver.init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW; - serial_driver.refcount = &serial_refcount; - serial_driver.table = serial_table; - serial_driver.termios = serial_termios; - serial_driver.termios_locked = serial_termios_locked; - - serial_driver.open = rs_open; - serial_driver.close = rs_close; - serial_driver.write = rs_write; - serial_driver.put_char = rs_put_char; - serial_driver.flush_chars = rs_flush_chars; - serial_driver.write_room = rs_write_room; - serial_driver.chars_in_buffer = rs_chars_in_buffer; - serial_driver.flush_buffer = rs_flush_buffer; - serial_driver.ioctl = rs_ioctl; - serial_driver.throttle = rs_throttle; - serial_driver.unthrottle = rs_unthrottle; - serial_driver.send_xchar = rs_send_xchar; - serial_driver.set_termios = rs_set_termios; - serial_driver.stop = rs_stop; - serial_driver.start = rs_start; - serial_driver.hangup = rs_hangup; - serial_driver.break_ctl = rs_break; - serial_driver.wait_until_sent = rs_wait_until_sent; - serial_driver.read_proc = rs_read_proc; - - /* - * Let's have a little bit of fun ! - */ - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - - if (state->type == PORT_UNKNOWN) continue; - - if (!state->irq) { - state->irq = ia64_alloc_vector(); - ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq); - } - - printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n", - state->line, - state->port, state->irq, - uart_config[state->type].name); - } - /* - * The callout device is just like normal device except for - * major number and the subtype code. - */ - callout_driver = serial_driver; - callout_driver.name = "cua"; - callout_driver.major = TTYAUX_MAJOR; - callout_driver.subtype = SERIAL_TYPE_CALLOUT; - callout_driver.read_proc = 0; - callout_driver.proc_entry = 0; - - if (tty_register_driver(&serial_driver)) - panic("Couldn't register simserial driver\n"); - - if (tty_register_driver(&callout_driver)) - panic("Couldn't register callout driver\n"); - - return 0; -} - -#ifndef MODULE -__initcall(simrs_init); -#endif